#!/bin/bash

# Flutter项目测试脚本
# 作者: AI助手
# 创建日期: $(date +"%Y-%m-%d")
# 用途: 为LaraPress Flutter应用运行完整的测试套件

set -e  # 遇到错误时立即退出

# 错误处理函数
handle_error() {
    local exit_code=$?
    local line_number=$1
    log_error "脚本在第 $line_number 行出错，退出码: $exit_code"
    log_error "详细日志已保存到: $LOG_FILE"
    
    # 清理临时文件
    cleanup_on_error
    
    exit $exit_code
}

# 错误清理函数
cleanup_on_error() {
    log_info "执行错误清理..."
    # 这里可以添加清理逻辑，比如删除临时文件等
}

# 设置错误陷阱
trap 'handle_error $LINENO' ERR

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 项目根目录
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$PROJECT_ROOT"

# 创建日志目录
LOG_DIR="$PROJECT_ROOT/logs"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/test_$(date +%Y%m%d_%H%M%S).log"

# 日志函数
log_info() {
    local msg="$1"
    echo -e "${BLUE}[INFO]${NC} $msg"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $msg" >> "$LOG_FILE"
}

log_success() {
    local msg="$1"
    echo -e "${GREEN}[SUCCESS]${NC} $msg"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $msg" >> "$LOG_FILE"
}

log_warning() {
    local msg="$1"
    echo -e "${YELLOW}[WARNING]${NC} $msg"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $msg" >> "$LOG_FILE"
}

log_error() {
    local msg="$1"
    echo -e "${RED}[ERROR]${NC} $msg"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $msg" >> "$LOG_FILE"
}

# 检查Flutter是否安装
check_flutter() {
    log_info "检查Flutter环境..."
    if ! command -v flutter &> /dev/null; then
        log_error "Flutter未安装或未添加到PATH中"
        exit 1
    fi
    
    flutter --version
    log_success "Flutter环境检查通过"
}

# 清理构建缓存
clean_build() {
    log_info "清理构建缓存..."
    flutter clean
    log_success "构建缓存清理完成"
}

# 获取依赖
get_dependencies() {
    log_info "获取项目依赖..."
    flutter pub get
    
    # 为每个本地包获取依赖
    local packages=("cms" "common" "components" "theme")
    for package in "${packages[@]}"; do
        if [ -d "larapress_app_package/$package" ]; then
            log_info "获取 $package 包的依赖..."
            cd "larapress_app_package/$package"
            flutter pub get
            cd "$PROJECT_ROOT"
        fi
    done
    
    log_success "所有依赖获取完成"
}

# 代码分析
analyze_code() {
    log_info "开始代码静态分析..."
    
    # 分析主项目
    log_info "分析主项目..."
    flutter analyze
    
    # 分析各个本地包
    local packages=("cms" "common" "components" "theme")
    for package in "${packages[@]}"; do
        if [ -d "larapress_app_package/$package" ]; then
            log_info "分析 $package 包..."
            cd "larapress_app_package/$package"
            flutter analyze
            cd "$PROJECT_ROOT"
        fi
    done
    
    log_success "代码静态分析完成"
}

# 运行单元测试
run_unit_tests() {
    log_info "开始运行单元测试..."
    
    # 运行主项目测试
    log_info "运行主项目测试..."
    if [ -d "test" ] && [ "$(find test -name '*.dart' | wc -l)" -gt 0 ]; then
        flutter test --coverage
    else
        log_warning "主项目没有找到测试文件"
    fi
    
    # 运行各个本地包的测试
    local packages=("cms" "common" "components" "theme")
    for package in "${packages[@]}"; do
        if [ -d "larapress_app_package/$package" ]; then
            log_info "运行 $package 包的测试..."
            cd "larapress_app_package/$package"
            if [ -d "test" ] && [ "$(find test -name '*.dart' | wc -l)" -gt 0 ]; then
                flutter test --coverage
            else
                log_warning "$package 包没有找到测试文件"
            fi
            cd "$PROJECT_ROOT"
        fi
    done
    
    log_success "单元测试完成"
}

# 验证baseUrl配置
validate_base_url() {
    log_info "验证baseUrl配置..."
    
    local http_file="larapress_app_package/common/lib/export/http.dart"
    
    # 检查文件是否存在
    if [ ! -f "$http_file" ]; then
        log_error "HTTP配置文件不存在: $http_file"
        return 1
    fi
    
    # 提取baseUrl
    local base_url=$(grep -o "baseUrl: '[^']*'" "$http_file" | sed "s/baseUrl: '\([^']*\)'/\1/")
    
    if [ -z "$base_url" ]; then
        log_error "未找到baseUrl配置"
        return 1
    fi
    
    log_info "发现baseUrl: $base_url"
    
    # 验证URL格式
    if [[ ! "$base_url" =~ ^https?:// ]]; then
        log_error "baseUrl格式无效，必须以 http:// 或 https:// 开头: $base_url"
        return 1
    fi
    
    # 安全性检查
    if [[ "$base_url" =~ ^http:// ]]; then
        log_warning "使用HTTP协议，生产环境建议使用HTTPS: $base_url"
    else
        log_success "使用HTTPS协议: $base_url"
    fi
    
    # 检查是否包含敏感信息
    local sensitive_patterns=("password" "token" "key" "secret" "admin")
    for pattern in "${sensitive_patterns[@]}"; do
        if [[ "$base_url" =~ $pattern ]]; then
            log_warning "baseUrl可能包含敏感信息: $pattern"
        fi
    done
    
    # 测试API连接性（可选）
    log_info "检查API连接性: $base_url"
    if command -v curl &> /dev/null; then
        if curl -s --max-time 10 --head "$base_url" > /dev/null 2>&1; then
            log_success "API连接测试通过: $base_url"
        else
            log_warning "API连接测试失败，但URL格式正确: $base_url"
        fi
    else
        log_warning "未安装curl，跳过API连接测试"
    fi
    
    log_success "baseUrl验证完成"
    log_info "当前API地址: $base_url"
}

# 运行集成测试
run_integration_tests() {
    log_info "检查集成测试..."
    
    if [ -d "integration_test" ] && [ "$(find integration_test -name '*.dart' | wc -l)" -gt 0 ]; then
        log_info "运行集成测试..."
        flutter test integration_test/
        log_success "集成测试完成"
    else
        log_warning "没有找到集成测试文件"
    fi
}

# 格式化代码检查
check_formatting() {
    log_info "检查代码格式..."
    
    # 检查主项目格式
    if ! dart format --set-exit-if-changed lib/ test/ 2>/dev/null; then
        log_warning "主项目代码格式需要修正"
        log_info "自动格式化主项目代码..."
        dart format lib/ test/
    fi
    
    # 检查各个本地包的格式
    local packages=("cms" "common" "components" "theme")
    for package in "${packages[@]}"; do
        if [ -d "larapress_app_package/$package" ]; then
            cd "larapress_app_package/$package"
            if ! dart format --set-exit-if-changed lib/ test/ 2>/dev/null; then
                log_warning "$package 包代码格式需要修正"
                log_info "自动格式化 $package 包代码..."
                dart format lib/ test/
            fi
            cd "$PROJECT_ROOT"
        fi
    done
    
    log_success "代码格式检查完成"
}

# 构建测试
build_test() {
    log_info "测试构建应用..."
    
    # Android构建测试
    log_info "测试Android构建..."
    flutter build apk --debug
    log_success "Android构建测试通过"
    
    # iOS构建测试 (仅在macOS上)
    if [[ "$OSTYPE" == "darwin"* ]]; then
        log_info "测试iOS构建..."
        flutter build ios --debug --no-codesign
        log_success "iOS构建测试通过"
    else
        log_warning "非macOS系统，跳过iOS构建测试"
    fi
}

# 生成测试报告
generate_report() {
    log_info "生成测试报告..."
    
    # 创建报告目录
    mkdir -p reports
    
    # 如果存在覆盖率文件，生成HTML报告
    if command -v genhtml &> /dev/null && [ -f "coverage/lcov.info" ]; then
        log_info "生成覆盖率HTML报告..."
        genhtml coverage/lcov.info -o reports/coverage
        log_success "覆盖率报告生成完成: reports/coverage/index.html"
    else
        log_warning "genhtml未安装或无覆盖率数据，跳过HTML报告生成"
    fi
    
    # 生成简单的测试总结
    cat > reports/test_summary.txt << EOF
Flutter项目测试总结
==================
测试时间: $(date)
项目路径: $PROJECT_ROOT

测试内容:
- ✅ Flutter环境检查
- ✅ 依赖获取
- ✅ 代码静态分析
- ✅ 单元测试
- ✅ 集成测试检查
- ✅ 代码格式检查
- ✅ 构建测试

详细日志请查看终端输出。
EOF
    
    log_success "测试总结报告生成: reports/test_summary.txt"
}

# 显示帮助信息
show_help() {
    echo "Flutter项目测试脚本"
    echo ""
    echo "用法: $0 [选项]"
    echo ""
    echo "选项:"
    echo "  -h, --help          显示此帮助信息"
    echo "  -c, --clean         仅清理构建缓存"
    echo "  -d, --deps          仅获取依赖"
    echo "  -a, --analyze       仅运行代码分析"
    echo "  -t, --test          仅运行测试"
    echo "  -f, --format        仅检查代码格式"
    echo "  -b, --build         仅测试构建"
    echo "  --baseurl-only      仅验证baseUrl配置"
    echo "  --no-clean          跳过清理步骤"
    echo "  --no-deps           跳过依赖获取"
    echo "  --no-analyze        跳过代码分析"
    echo "  --no-test           跳过测试"
    echo "  --no-format         跳过格式检查"
    echo "  --no-build          跳过构建测试"
    echo "  --verbose           显示详细输出"
    echo "  --config FILE       指定配置文件（默认: test_config.yaml）"
    echo "  --log-level LEVEL   设置日志级别（debug|info|warning|error）"
    echo ""
    echo "示例:"
    echo "  $0                  运行完整测试套件"
    echo "  $0 --test           仅运行测试"
    echo "  $0 --no-build       运行除构建外的所有测试"
    echo "  $0 --verbose        显示详细输出"
}

# 计时函数
start_timer() {
    TIMER_START=$(date +%s)
}

end_timer() {
    local TIMER_END=$(date +%s)
    local DURATION=$((TIMER_END - TIMER_START))
    local MINUTES=$((DURATION / 60))
    local SECONDS=$((DURATION % 60))
    log_success "执行完成，总耗时: ${MINUTES}分${SECONDS}秒"
}

# 主函数
main() {
    start_timer
    local run_clean=true
    local run_deps=true
    local run_analyze=true
    local run_test=true
    local run_format=true
    local run_build=true
    local only_mode=false
    
    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help
                exit 0
                ;;
            -c|--clean)
                only_mode=true
                run_clean=true
                run_deps=false
                run_analyze=false
                run_test=false
                run_format=false
                run_build=false
                ;;
            -d|--deps)
                only_mode=true
                run_clean=false
                run_deps=true
                run_analyze=false
                run_test=false
                run_format=false
                run_build=false
                ;;
            -a|--analyze)
                only_mode=true
                run_clean=false
                run_deps=false
                run_analyze=true
                run_test=false
                run_format=false
                run_build=false
                ;;
            -t|--test)
                only_mode=true
                run_clean=false
                run_deps=false
                run_analyze=false
                run_test=true
                run_format=false
                run_build=false
                ;;
            -f|--format)
                only_mode=true
                run_clean=false
                run_deps=false
                run_analyze=false
                run_test=false
                run_format=true
                run_build=false
                ;;
            -b|--build)
                only_mode=true
                run_clean=false
                run_deps=false
                run_analyze=false
                run_test=false
                run_format=false
                run_build=true
                ;;
            --baseurl-only)
                only_mode=true
                run_clean=false
                run_deps=false
                run_analyze=false
                run_test=false
                run_format=false
                run_build=false
                # 直接运行baseUrl验证
                validate_base_url
                exit $?
                ;;
            --no-clean)
                run_clean=false
                ;;
            --no-deps)
                run_deps=false
                ;;
            --no-analyze)
                run_analyze=false
                ;;
            --no-test)
                run_test=false
                ;;
            --no-format)
                run_format=false
                ;;
            --no-build)
                run_build=false
                ;;
            *)
                log_error "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
        shift
    done
    
    # 显示开始信息
    log_info "开始Flutter项目测试..."
    log_info "项目路径: $PROJECT_ROOT"
    
    # 计算总步骤数
    local total_steps=0
    local current_step=0
    [ "$run_clean" = true ] && ((total_steps++))
    [ "$run_deps" = true ] && ((total_steps++))
    [ "$run_analyze" = true ] && ((total_steps++))
    [ "$run_format" = true ] && ((total_steps++))
    [ "$run_test" = true ] && ((total_steps++))
    [ "$run_build" = true ] && ((total_steps++))
    
    log_info "计划执行 $total_steps 个步骤"
    
    # 检查Flutter环境
    check_flutter
    
    # 执行测试步骤
    if [ "$run_clean" = true ]; then
        ((current_step++))
        log_info "[$current_step/$total_steps] 执行清理步骤"
        clean_build
    fi
    
    if [ "$run_deps" = true ]; then
        ((current_step++))
        log_info "[$current_step/$total_steps] 执行依赖获取"
        get_dependencies
    fi
    
    if [ "$run_analyze" = true ]; then
        ((current_step++))
        log_info "[$current_step/$total_steps] 执行代码分析"
        analyze_code
    fi
    
    if [ "$run_format" = true ]; then
        ((current_step++))
        log_info "[$current_step/$total_steps] 执行格式化检查"
        check_formatting
    fi
    
    if [ "$run_test" = true ]; then
        ((current_step++))
        log_info "[$current_step/$total_steps] 执行测试"
        validate_base_url
        run_unit_tests
        run_integration_tests
    fi
    
    if [ "$run_build" = true ]; then
        ((current_step++))
        log_info "[$current_step/$total_steps] 执行构建测试"
        build_test
    fi
    
    # 生成报告（仅在完整测试时）
    if [ "$only_mode" = false ]; then
        generate_report
    fi
    
    log_success "🎉 所有测试完成！"
    end_timer
    log_info "日志文件保存在: $LOG_FILE"
}

# 运行主函数
main "$@"
